package com.iims.flowable.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.iims.common.core.domain.AjaxResult;
import com.iims.common.core.page.TableDataInfo;
import com.iims.flowable.common.constant.FlowableConstant;
import com.iims.flowable.common.enums.CommentTypeEnum;
import com.iims.flowable.factory.BaseFlowableController;
import com.iims.flowable.flow.vo.ExecuteTaskDataVo;
import com.iims.flowable.flow.vo.request.FlowTaskQueryVo;
import com.iims.flowable.flow.vo.resp.FlowHasDoTaskDto;
import com.iims.flowable.flow.vo.resp.FlowTaskTypeResponse;
import com.iims.flowable.flow.vo.wrapper.WrapperFlowTaskDoneList;
import com.iims.flowable.flow.vo.wrapper.WrapperFlowTaskToDoList;
import com.iims.flowable.service.IFlowTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryProperty;
import org.flowable.task.service.impl.TaskQueryProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程查询区
 */
@Slf4j
@Api(tags = "流程任务")
@ApiSort(4)
@RestController
@RequestMapping("/flowable/task")
public class FlowTaskQueryController extends BaseFlowableController {

    @Autowired
    private IFlowTaskService flowTaskService;


    private static final Map<String, QueryProperty> allowedSortProperties = new HashMap<>();

    static {
        allowedSortProperties.put("deleteReason", HistoricTaskInstanceQueryProperty.DELETE_REASON);
        allowedSortProperties.put("duration", HistoricTaskInstanceQueryProperty.DURATION);
        allowedSortProperties.put("endTime", HistoricTaskInstanceQueryProperty.END);
        allowedSortProperties.put(FlowableConstant.EXECUTION_ID, HistoricTaskInstanceQueryProperty.EXECUTION_ID);
        allowedSortProperties.put("taskInstanceId", HistoricTaskInstanceQueryProperty.HISTORIC_TASK_INSTANCE_ID);
        allowedSortProperties.put(FlowableConstant.PROCESS_DEFINITION_ID, HistoricTaskInstanceQueryProperty.PROCESS_DEFINITION_ID);
        allowedSortProperties.put(FlowableConstant.PROCESS_INSTANCE_ID, HistoricTaskInstanceQueryProperty.PROCESS_INSTANCE_ID);
        allowedSortProperties.put("assignee", HistoricTaskInstanceQueryProperty.TASK_ASSIGNEE);
        allowedSortProperties.put(FlowableConstant.TASK_DEFINITION_KEY, HistoricTaskInstanceQueryProperty.TASK_DEFINITION_KEY);
        allowedSortProperties.put("description", HistoricTaskInstanceQueryProperty.TASK_DESCRIPTION);
        allowedSortProperties.put("dueDate", HistoricTaskInstanceQueryProperty.TASK_DUE_DATE);
        allowedSortProperties.put(FlowableConstant.NAME, HistoricTaskInstanceQueryProperty.TASK_NAME);
        allowedSortProperties.put("owner", HistoricTaskInstanceQueryProperty.TASK_OWNER);
        allowedSortProperties.put("priority", HistoricTaskInstanceQueryProperty.TASK_PRIORITY);
        allowedSortProperties.put(FlowableConstant.TENANT_ID, HistoricTaskInstanceQueryProperty.TENANT_ID_);
        allowedSortProperties.put("startTime", HistoricTaskInstanceQueryProperty.START);
    }

    //@ApiOperation(value = "获取任务分类列表", response = FlowTaskTypeResponse.class)
    @ApiOperationSupport(order = 2)
    @GetMapping(value = "/typeList")
    public AjaxResult typeList() throws Exception {
        CommentTypeEnum[] typeEnums = CommentTypeEnum.values();
        List<FlowTaskTypeResponse> typeResponses = new ArrayList<>(typeEnums.length);
        for (CommentTypeEnum typeEnum : typeEnums) {
            FlowTaskTypeResponse ftresp = new FlowTaskTypeResponse();
            ftresp.setType(typeEnum.toString());
            ftresp.setTypeDesc(typeEnum.getName());
            typeResponses.add(ftresp);
        }
        return AjaxResult.success(typeResponses);
    }

    @ApiOperation(value = "待办任务", response = FlowHasDoTaskDto.class)
    @ApiOperationSupport(order = 3, ignoreParameters = {"orderByColumn", "isAsc"})
    @GetMapping(value = "/todoList")
    public TableDataInfo todoList(FlowTaskQueryVo taskQueryVo) throws Exception {
        taskQueryVo.setTaskType(FlowTaskQueryVo.ListQUeryTaskType.ToDo);
        //taskQueryVo.setPageDomain(getPageDomain());
        TaskQuery query = taskService.createTaskQuery();
        return this.pageList(taskQueryVo, query, WrapperFlowTaskToDoList.class, allowedSortProperties, TaskQueryProperty.CREATE_TIME);
    }

    //@ApiOperation(value = "待阅任务", response = FlowHasDoTaskDto.class)
    @ApiOperationSupport(order = 4, ignoreParameters = {"orderByColumn", "isAsc"})
    @GetMapping(value = "/listToRead")
    public TableDataInfo listToRead(FlowTaskQueryVo taskQueryVo) throws Exception {
        taskQueryVo.setTaskType(FlowTaskQueryVo.ListQUeryTaskType.ToRead);
        //taskQueryVo.setPageDomain(getPageDomain());
        TaskQuery query = taskService.createTaskQuery();
        return this.pageList(taskQueryVo, query, WrapperFlowTaskToDoList.class, allowedSortProperties, TaskQueryProperty.CREATE_TIME);
    }

    @ApiOperation(value = "已办任务", response = FlowHasDoTaskDto.class)
    @ApiOperationSupport(order = 5, ignoreParameters = {"orderByColumn", "isAsc"})
    @ApiImplicitParam(value = "排序列", name = "orderByColumn", paramType = "query")
    @GetMapping(value = "/finishedList")
    public TableDataInfo finishedList(FlowTaskQueryVo taskQueryVo) throws Exception {
        taskQueryVo.setTaskType(FlowTaskQueryVo.ListQUeryTaskType.Finished);
        //taskQueryVo.setPageDomain(getPageDomain());
        HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery();
        return this.pageList(taskQueryVo, query, WrapperFlowTaskDoneList.class, allowedSortProperties);
    }

    //2021-06-28 弃用
    //@ApiOperation(value = "查询任务详情", response = TaskDetailResponse.class)
    //@ApiOperationSupport(order = 6)
    // @GetMapping(value = "/queryById/{taskId}")
    public AjaxResult queryById(@ApiParam(value = "任务Id", required = true) @PathVariable String taskId) {
        return AjaxResult.success(flowTaskService.getTask(taskId));
    }

    //@ApiOperation(value = "获取任务表单", notes = "返回表单JSON数据对象,前端需要解析成表单页面")
    //@ApiOperationSupport(order = 7)
    //@GetMapping(value = "/renderedTaskForm/{taskId}")
    public AjaxResult renderedTaskForm(@ApiParam(value = "任务Id", required = true) @PathVariable String taskId) {
        permissionService.validateReadPermissionOnTask2(taskId, getLoginUserCode(), true, true);
        Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
        return AjaxResult.success(renderedTaskForm);
    }

    @ApiOperation(value = "获取任务执行表单数据(历史+当前)", response = ExecuteTaskDataVo.class)
    @ApiOperationSupport(order = 9)
    @GetMapping(value = "/executeTaskData/{taskId}")
    public AjaxResult executeTaskData(@ApiParam(value = "任务Id", required = true) @PathVariable String taskId) {
        TaskInfo task = flowTaskService.getTaskByTaskId(taskId);
        Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        UserTask userTask = (UserTask) process.getFlowElement(task.getTaskDefinitionKey(), true);
        if (userTask == null) {
            throw new FlowableObjectNotFoundException("Can not find userTask by id " + task.getTaskDefinitionKey());
        }

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .orderByStartTime().asc()
                .singleResult();

        ExecuteTaskDataVo executeTaskDataVo = new ExecuteTaskDataVo();
        executeTaskDataVo.setStartUserId(processInstance.getStartUserId());
        // 当前任务是发起者
        if (FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey())) {
            executeTaskDataVo.setInitiator(true);
        }

        //获取起始任务数据表单
        initStartDataFormBack(
                processInstance.getProcessDefinitionId(), processInstance.getProcessDefinitionKey(),
                processInstance.getProcessInstanceId(), processInstance.getBusinessKey(), executeTaskDataVo);


        //获取当前任务
        String taskFormKey = formService.getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
        Object renderedTaskForm = cmisFormService.selectFlowableFormUIByKey(taskFormKey);
        executeTaskDataVo.setTaskFormKey(taskFormKey);
        executeTaskDataVo.setRenderedTaskForm(renderedTaskForm);

        //executeTaskDataVo.setVariables(variables);
        //获取历史表单
        executeTaskDataVo.setHistoryTaskForms(cmisTaskFormService.getRenderedTaskForms(task.getProcessInstanceId()));
        return AjaxResult.success(executeTaskDataVo);
    }

}
